/**
 * @Author:Geln Yang
 * @Created:2008-9-15 $ Revision: 1.0 $ $ Author: Geln Yang $ $ Date: 2008-9-15 $
 */
package org.geln.web.util;

import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.swing.Timer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @Author:Geln Yang
 * @Created:2008-9-15
 */
public class URLUtils {
	public static final Log logger = LogFactory.getLog(URLUtils.class);
	public static int MAX_URL_LENGTH = 100;
	public static int TIMER_INTERRUPT = 1000;
	public static int MAX_TIME_FOR_GET_STREAM = 5000;
	public static final String URL_REGEX = "(http|https|ftp)://" // protocal
			+ "([a-z\\d]+([a-z\\d-_]*[a-z\\d]+)?\\.)+[a-z]{2,}" // host
			+ "(:\\d{2,5})?" // port
			+ "(" // begin of url path
			+ "/" // is there '/' after host
			+ "(" // begin of url exact path
			+ "([^\\?/:\\.]+/)*([^\\?/:\\.]+)?" // folders
			+ "(\\.[a-z\\d]+)?" // name+suffix
			+ "((\\?)|((\\?[^\\?&:]+=[^\\?&=]*)(&[^\\?&:]+=[^\\?&=]*)*))?"// queryString
			+ ")?" // end
			+ ")?"; // end
	static Timer timer;
	static Thread thread;

	public static String getIpAddress(String url) {
		try {
			return InetAddress.getByName(url).getHostAddress();
		} catch (UnknownHostException e) {
			return null;
		}
	}

	/**
	 * build the original URL address from {@link HttpServletRequest}
	 */
	@SuppressWarnings("unchecked")
	public static String buildOriginalURL(HttpServletRequest request) {
		StringBuffer originalURL = request.getRequestURL();
		Map<String, String[]> parameters = request.getParameterMap();
		if (parameters != null && parameters.size() > 0) {
			originalURL.append("?");
			for (Iterator<String> iter = parameters.keySet().iterator(); iter.hasNext();) {
				String key = (String) iter.next();
				String[] values = parameters.get(key);
				for (int i = 0; i < values.length; i++) {
					originalURL.append(key).append("=").append(values[i]).append("&");
				}
			}
		}
		return originalURL.toString();
	}

	/**
	 * judge a URL address whether it's valid. <br/><br/>
	 * <ul>
	 * <li> if the URL address match {@LINK URLUtils.URL_REGEX},return true;</li>
	 * <li> else return false;</li>
	 * </ul>
	 * 
	 * @param String:url
	 */
	public static boolean isValidUrl(String url) {
		return url.toLowerCase().matches(URL_REGEX);
	}

	public static InputStreamReader getHTML(String url, int time) {
		if (url.length() > MAX_URL_LENGTH)
			return null;
		try {
			URL u = new URL(url);
			return getHTML(u, time);
		} catch (MalformedURLException e) {
			logger.error(e.getMessage(),e);
			return null;
		}
	}

	public static InputStreamReader getHTML(URL url, int time) {
		if (url != null) {
			try {
				URLConnection conn = url.openConnection();
				conn.setConnectTimeout(time);
				conn.setReadTimeout(time);
				return new InputStreamReader(conn.getInputStream());
			} catch (IOException e) {
				logger.debug("Can't open stream on " + url.toString());
			}
		}
		return null;
	}

	/**
	 * @param url
	 * @return
	 */
	public static InputStreamReader getHTML(URL url) {
		return getHTML(url, MAX_TIME_FOR_GET_STREAM);
	}

	/**
	 * @param url
	 * @return
	 */
	public static InputStreamReader getHTML(String url) {
		if (url.length() > MAX_URL_LENGTH)
			return null;
		try {
			URL u = new URL(url);
			return getHTML(u);
		} catch (MalformedURLException e) {
			logger.error(e.getMessage(),e);
			return null;
		}
	}

	/**
	 * @param max_url_length
	 */
	public static void setMAX_URL_LENGTH(int max_url_length) {
		MAX_URL_LENGTH = max_url_length;
	}

	/**
	 * @param url
	 * @return
	 */
	public static boolean isValid(String url) {
		return url.matches(URL_REGEX);

	}

	/**
	 * @param url
	 * @return
	 */
	public static String getHostRoot(String url) {
		try {
			return getHostRoot(new URL(url));
		} catch (MalformedURLException e) {
			return null;
		}
	}

	/**
	 * @param url
	 * @return
	 */
	public static String getHostRoot(URL url) {
		if (url == null) {
			return null;
		}
		String protocal = url.getProtocol();
		String host = url.getHost();

		int port = url.getPort();
		if (port == -1) {
			return protocal + "://" + host + "/";
		} else {
			return protocal + "://" + host + ":" + port + "/";
		}
	}

	/**
	 * @param url
	 * @return
	 */
	public static String getFileName(String u) {
		String url = u;
		if (url != null) {
			url = url.replaceAll("\\\\", "/");
			String linkFile = getLinkFile(url);
			if ("".equals(linkFile)) {
				return null;
			} else {
				int end = linkFile.indexOf("?");
				if (end > 0) {
					return linkFile.substring(0, end);
				} else {
					return linkFile;
				}
			}
		}
		return null;
	}

	/**
	 * @param url
	 * @return
	 */
	public static String getFileName(URL url) {
		return getFileName(url.toString());
	}

	/**
	 * Given the url "http://www.a.com/a/b/c.html?a=1&b=2",the result would be "c.html?a=1&b=2".
	 * 
	 * @param url
	 * @return
	 */
	public static String getLinkFile(String url) {
		//String url = u;
		if (url != null) {
			url = url.replaceAll("\\\\", "/");
			String relativePath = getURLRelativePath(url);
			if (relativePath != null && relativePath.length() < url.length()) {
				return url.substring(relativePath.length());
			}
		}
		return "";
	}

	/**
	 * See the method getLinkFile(URL url) ;
	 * 
	 * @param url
	 * @return
	 */
	public static String getLinkFile(URL url) {
		return getFileName(url.toString());
	}

	public static String getURLPath(String u) {
		String url = u;
		if (url == null)
			return null;
		try {
			return getURLPath(new URL(url.replaceAll("\\\\", "/")));
		} catch (Exception e) {
			return null;
		}
	}

	public static String getURLPath(URL url) {
		String hostRoot = getHostRoot(url);
		if (hostRoot == null) {
			return null;
		}
		if (url.toString().length() <= hostRoot.length()) {
			return "/";
		}
		String urlPath = url.toString().substring(hostRoot.length() - 1);
		// System.out.println(urlPath);

		if (urlPath.indexOf("?") > 0) {
			urlPath = urlPath.substring(0, urlPath.indexOf("?"));
			urlPath = urlPath.substring(0, urlPath.lastIndexOf("/"));
		}

		// System.out.println(urlPath);

		if (urlPath.lastIndexOf(".") > urlPath.lastIndexOf("/")) {
			urlPath = urlPath.substring(0, urlPath.lastIndexOf("/"));
		}

		// System.out.println(urlPath);
		// System.out.println();

		if (!urlPath.endsWith("/")) {
			urlPath = urlPath + "/";
		}
		return urlPath;
	}

	/**
	 * @param u
	 * @return
	 */
	public static String getURLRelativePath(String url) {
		try {
			return getURLRelativePath(new URL(url));
		} catch (Exception e) {
			return getURLPath(url);
		}

	}

	/**
	 * @param url
	 * @return
	 */
	public static String getURLRelativePath(URL url) {
		// return getURLRelativePath(url.toString());
		String urlPath = getURLPath(url);
		if (urlPath == null) {
			return null;
		}
		String protocal = url.getProtocol();
		String host = url.getHost();
		int port = url.getPort();
		if (port == -1) {
			return protocal + "://" + host + urlPath;
		} else {
			return protocal + "://" + host + ":" + port + urlPath;
		}

	}

	/**
	 * @param path
	 * @param floors
	 * @return
	 */
	public static String toUpperRelativePath(String path, int floors) {
		String tempurl = path;
		if (path.endsWith("/")) {
			floors++;
		}
		for (int i = 0; i < floors; i++) {
			tempurl = tempurl.substring(0, tempurl.lastIndexOf("/"));
		}
		if (isValid(tempurl)) {
			return tempurl + "/";
		} else {
			return getHostRoot(path);
		}

	}
}
